package com.example.websocket.handler;

import com.example.websocket.enums.SupportType;
import com.example.websocket.util.WSSessionUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;

import java.util.Comparator;
import java.util.List;

@Slf4j
public class DefaultWebSocketHandler extends TextWebSocketHandler implements RegisterWebSocketHandler {

    /**
     * String[]{"/api/osd/ws/**"}
     * */
    protected final String[] paths;

    protected final List<OrderdWebSocketHandler> handlers;

    public DefaultWebSocketHandler(String[] paths, List<OrderdWebSocketHandler> handlers) {
        this.paths = paths;
        this.handlers = handlers;
        this.handlers.sort(Comparator.comparing(OrderdWebSocketHandler::getOrder));
    }

    /**
     * Invoked after WebSocket negotiation has succeeded and the WebSocket connection is opened and ready for use.
     */
    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        String uniqueCode = getUniqueCode(session);
        WSSessionUtil.addSession(session, uniqueCode);
        for (OrderdWebSocketHandler orderdWebSocketHandler : handlers) {
            if (orderdWebSocketHandler.support(SupportType.after_connection,session,null)) {
                orderdWebSocketHandler.afterConnectionEstablished(session);
            }
        }
    }


    public void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
        String payload = message.getPayload();
        for (OrderdWebSocketHandler orderdWebSocketHandler : handlers) {
            if (orderdWebSocketHandler.support(SupportType.handle_message,session,payload)) {
                orderdWebSocketHandler.handleMessage(session,message);
            }
        }
    }

    /**
     * Handle an error from the underlying WebSocket message transport.
     */
    @Override
    public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
        for (OrderdWebSocketHandler orderdWebSocketHandler : handlers) {
            if (orderdWebSocketHandler.support(SupportType.handle_transport_error,session,exception)) {
                orderdWebSocketHandler.handleTransportError(session,exception);
            }
        }
    }


    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) throws Exception {
        try {
            for (OrderdWebSocketHandler orderdWebSocketHandler : handlers) {
                if (orderdWebSocketHandler.support(SupportType.after_connection_closed,session,closeStatus)) {
                    orderdWebSocketHandler.afterConnectionClosed(session,closeStatus);
                }
            }
        }finally {
            String uniqueCode = getUniqueCode(session);
            WSSessionUtil.remove(session,uniqueCode);
        }
    }
    @Override
    public String[] paths() {
        return paths;
    }
}
